﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace JweDemo
{
    public static class DateTimeExtensions
    {
        /// <summary>
        /// Returns number of seconds since Unix epoch based on datetime that user provide.
        /// </summary>
        /// <param name="utcDateTime">A UTC datetime</param>
        /// <returns>String representing number of seconds since Unix epoch</returns>
        public static string ToNumericDateString(this DateTime utcDateTime)
        {
            TimeSpan timeSinceEpoch = utcDateTime.ToUniversalTime() - System.IdentityModel.Tokens.EpochTime.UnixEpoch;
            return Math.Floor(timeSinceEpoch.TotalSeconds).ToString();
        }

    }

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("[START PROGRAM]");

            //Demo();

            Console.WriteLine("[END PROGRAM]");
            Console.ReadLine();
        }

        public static void Demo2()
        {
            System.Security.Cryptography.RandomNumberGenerator randomNumberGenerator = randomNumberGenerator = System.Security.Cryptography.RandomNumberGenerator.Create();
            byte[] symmetricKeyBytes = new byte[256 / 8];
            randomNumberGenerator.GetBytes(symmetricKeyBytes);
            System.IdentityModel.Tokens.InMemorySymmetricSecurityKey securityKey =
                new System.IdentityModel.Tokens.InMemorySymmetricSecurityKey(symmetricKeyBytes);

            System.IdentityModel.Tokens.EncryptingCredentials cred = null;
            cred = new System.IdentityModel.Tokens.EncryptingCredentials();
            cred.SecurityKey = securityKey;
            //cred.SecurityKeyIdentifier= securityKey;
            cred.Algorithm = "asd";

            System.Security.Cryptography.X509Certificates.X509Certificate2 cert = new System.Security.Cryptography.X509Certificates.X509Certificate2();

            //new System.IdentityModel.Tokens.EncryptingCredentials(
            //            securityKey,
            //            System.IdentityModel.Tokens.SecurityKeyIdentifier,
            //            System.IdentityModel.Tokens.SecurityAlgorithms.RsaSha256Signature

            //            ),
        }

        public static void Demo()
        {
            
            System.IdentityModel.Tokens.JwtSecurityTokenHandler tokenHandler = null;
            System.IdentityModel.Tokens.TokenValidationParameters validationParameters = null;
            System.Security.Cryptography.RandomNumberGenerator randomNumberGenerator = null;
            byte[] symmetricKey = null;
            System.IdentityModel.Tokens.InMemorySymmetricSecurityKey securityKey = null;
            string tokenIssuerName = string.Empty;
            string applyToAddress = string.Empty;
            int tokenDuration = 60;
            System.Security.Claims.Claim[] TestClaims = new System.Security.Claims.Claim[]
            {
                new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Name, "Cocadre Test User"),
                new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Role, "Test"),
                new System.Security.Claims.Claim(System.IdentityModel.Tokens.JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), // JWT ID
                new System.Security.Claims.Claim(System.IdentityModel.Tokens.JwtRegisteredClaimNames.Iat, DateTime.UtcNow.ToNumericDateString()), // Issued At
                new System.Security.Claims.Claim(System.IdentityModel.Tokens.JwtRegisteredClaimNames.Sub, "Testing") // Subject
            };

            tokenHandler = new System.IdentityModel.Tokens.JwtSecurityTokenHandler();
            randomNumberGenerator = System.Security.Cryptography.RandomNumberGenerator.Create();

            string base64SymmetricKeyString = ConfigurationManager.AppSettings["JWT:SymmetricKey"];

            if (string.IsNullOrWhiteSpace(base64SymmetricKeyString))
            {
                throw new Exception("Missing appSettings [JWT: SymmetricKey]");
            }

            try
            {
                symmetricKey = Convert.FromBase64String(base64SymmetricKeyString);
                securityKey = new System.IdentityModel.Tokens.InMemorySymmetricSecurityKey(symmetricKey);
            }
            catch (Exception)
            {
                throw;
            }

            tokenIssuerName = ConfigurationManager.AppSettings["JWT:TokenDescriptor:TokenIssuerName"] ?? string.Empty;
            applyToAddress = ConfigurationManager.AppSettings["JWT:TokenDescriptor:ApplyToAddress"] ?? string.Empty;

            validationParameters = new System.IdentityModel.Tokens.TokenValidationParameters()
            {
                
                ValidIssuer = tokenIssuerName,
                ValidAudience = applyToAddress,
                IssuerSigningToken = new System.ServiceModel.Security.Tokens.BinarySecretSecurityToken(symmetricKey)
            };

            if (!int.TryParse(ConfigurationManager.AppSettings["JWT:TokenDescriptor:TokenDuration"], out tokenDuration))
            {
                tokenDuration = 14; // default token can last for 14 days.
            }

            DateTime now = DateTime.UtcNow;

            System.IdentityModel.Tokens.InMemorySymmetricSecurityKey encSecurityKey = null;
            System.IdentityModel.Tokens.SecurityKeyIdentifier encSecurityKeyIdentifier = null;

            System.IdentityModel.Tokens.SecurityTokenDescriptor tokenDescriptor =
                new System.IdentityModel.Tokens.SecurityTokenDescriptor
                {
                    Subject = new System.Security.Claims.ClaimsIdentity(TestClaims),
                    TokenIssuerName = tokenIssuerName,
                    AppliesToAddress = applyToAddress,
                    Lifetime = new System.IdentityModel.Protocols.WSTrust.Lifetime(now, now.AddDays(tokenDuration)),
                    SigningCredentials = new System.IdentityModel.Tokens.SigningCredentials(
                        securityKey,
                        System.IdentityModel.Tokens.SecurityAlgorithms.HmacSha256Signature,
                        System.IdentityModel.Tokens.SecurityAlgorithms.Sha256Digest)
                    
                };

            System.IdentityModel.Tokens.SecurityToken token = tokenHandler.CreateToken(tokenDescriptor);

            Console.WriteLine(tokenHandler.WriteToken(token));
        }
    }
}
